﻿using System.Linq;

namespace Language.Utility
{
    internal static class DeclarationPrinter
    {
        #region Public Functions

        public static string Format( Stub.DetailedContext stub )
        {
            Stub.Class @class = stub as Stub.Class;

            if ( @class != null )
                return Format( @class );

            Stub.Function function = stub as Stub.Function;

            if ( function != null )
                return Format( function );

            Stub.Property property = stub as Stub.Property;

            if ( property != null )
                return Format( property );

            Stub.Enum @enum = stub as Stub.Enum;

            if ( @enum != null )
                return Format( @enum );

            Stub.Option option = stub as Stub.Option;

            if ( option != null )
                return Format( option );

            return null;
        }

        public static string Format( Stub.Enum stub )
        {
            return $"{Format( stub.Configuration )} enum {stub.Name}".Trim();
        }

        public static string Format( Stub.Option stub )
        {
            return $"{stub.Parent.Name}.{stub.Name}";
        }

        public static string Format( Stub.Class stub )
        {
            string extends = string.IsNullOrEmpty( stub.TypeDeclaration.Name ) ? string.Empty : $"extends {stub.TypeDeclaration.Name}";
            return $"{Format( stub.Configuration )} class {stub.Name} {extends}".Trim();
        }

        public static string Format( Stub.Property stub )
        {
            return $"{Format( stub.Configuration )} var {stub.Name} : {stub.TypeDeclaration.Name}".Trim();
        }

        public static string Format( Stub.Function stub )
        {
            string parameters = string.Join( ", ", from parameter in stub.Parameters select $"{parameter.Name} : {parameter.TypeDeclaration.Name}" );
            string @return = string.IsNullOrEmpty( stub.TypeDeclaration.Name ) ? string.Empty : $" : {stub.TypeDeclaration.Name}";
            return $"{Format( stub.Configuration )} function {stub.Name}({parameters}){@return}".Trim();
        }

        public static string Format( Stub.Configuration configuration )
        {
            string native = configuration.IsNative ? "import" : string.Empty;
            string @static = configuration.IsStatic ? "static" : string.Empty;
            string access = configuration.IsPrivate ? "private" : configuration.IsProtected ? "protected" : "public";
            return string.Join( " ", native, @static, access );
        }

        #endregion Public Functions
    }
}
